package com.linkallcloud.web.face.base;

import java.util.Arrays;
import java.util.List;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.linkallcloud.core.domain.TreeDomain;
import com.linkallcloud.core.dto.CheckResult;
import com.linkallcloud.core.dto.Trace;
import com.linkallcloud.core.dto.Tree;
import com.linkallcloud.core.exception.BizException;
import com.linkallcloud.core.exception.Exceptions;
import com.linkallcloud.core.face.message.request.IdFaceRequest;
import com.linkallcloud.core.face.message.request.ParentIdFaceRequest;
import com.linkallcloud.core.lang.Strings;
import com.linkallcloud.core.manager.ITreeManager;
import com.linkallcloud.core.www.ISimpleUser;
import com.linkallcloud.web.face.annotation.Face;

public abstract class BaseTreeFace2<T extends TreeDomain, S extends ITreeManager<T>> extends BaseFace2<T, S> {

    public BaseTreeFace2() {
        super();
    }

    @Face(simple = true)
    @RequestMapping(value = "/loadLevel1DomainTree", method = RequestMethod.POST)
    public @ResponseBody Object loadLevel1DomainTree(IdFaceRequest fr, CheckResult cr, Trace t, ISimpleUser su) {
        return doLoadLevel1DomainTree(t, fr, su, cr);
    }

    public List<T> doLoadLevel1DomainTree(Trace t, IdFaceRequest fr, ISimpleUser su, CheckResult cr) {
        return manager().loadLevel1DomainTree(t, false);
    }

    @Face(simple = true)
    @RequestMapping(value = "/loadDirectDomainTreeNodes", method = RequestMethod.POST)
    public @ResponseBody Object loadDirectDomainTreeNodes(IdFaceRequest fr, CheckResult cr, Trace t, ISimpleUser su) {
        return doLoadDirectDomainTreeNodes(t, fr, su, cr);
    }

    public List<T> doLoadDirectDomainTreeNodes(Trace t, IdFaceRequest fr, ISimpleUser su, CheckResult cr) {
        return manager().loadDirectDomainTreeNodes(t, fr.sid(), false);
    }

    /**
     * 整棵树一次性加载，适用于小数据量场景
     * 
     * @param fr
     * @param cr
     * @param t
     * @param su
     * @return
     */
    @Face(simple = true)
    @RequestMapping(value = "/loadDomainTrees", method = RequestMethod.POST)
    public @ResponseBody Object loadDomainTrees(IdFaceRequest fr, CheckResult cr, Trace t, ISimpleUser su) {
        // check(t, "loadTree", fr, su);

        T root = doLoadDomainTrees(t, fr, su, cr);
        return root.getChildren();
    }

    public T doLoadDomainTrees(Trace t, IdFaceRequest fr, ISimpleUser su, CheckResult cr) {
        return manager().getDomainTree(t, false);
    }

    @Face(simple = true)
    @RequestMapping(value = "/loadTree", method = RequestMethod.POST)
    public @ResponseBody Object loadTree(IdFaceRequest fr, CheckResult cr, Trace t, ISimpleUser su) {
        // check(t, "loadTree", fr, su);

        return doLoadTree(t, fr, su, cr);
    }

    public List<Tree> doLoadTree(Trace t, IdFaceRequest fr, ISimpleUser su, CheckResult cr) {
        Tree root = manager().getTree(t, false);
        return Arrays.asList(root);
    }

    @Override
    protected T doFetch(Trace t, ParentIdFaceRequest fr, ISimpleUser su, CheckResult cr) {
        T entity = super.doFetch(t, fr, su, cr);
        if (entity.getParentId() != null && entity.getParentId().longValue() > 0) {
            T parent = manager().fetchById(t, entity.getParentId());
            if (parent != null) {
                entity.setParentName(parent.getName());
            }
        }
        if (fr.getParentId() != null && entity.getId() == null) {
            entity.setParentId(fr.getParentId());
            entity.setParentClass(fr.getParentClass());
        }
        return entity;
    }

    @Face(simple = true)
    @RequestMapping(value = "/fetchParent", method = RequestMethod.POST)
    public @ResponseBody Object fetchParent(ParentIdFaceRequest faceReq, CheckResult cr, Trace t, ISimpleUser su) {
        // check(t, "fetchParent", faceReq, su);
        return doFetchParent(t, faceReq, su, cr);
    }

    private Object doFetchParent(Trace t, ParentIdFaceRequest faceReq, ISimpleUser su, CheckResult cr) {
        if (faceReq.getId() == null || Strings.isBlank(faceReq.getUuid())) {
            throw new BizException(Exceptions.CODE_ERROR_PARAMETER, "参数错误");
        }
        T entity = doFetch(t, faceReq, su, cr);
        if (entity != null && entity.getParentId() != null) {
            T parent = manager().fetchById(t, entity.getParentId());
            return convert(t, "fetch", faceReq, parent);
        }
        return null;
    }

    @Face(simple = true)
    @RequestMapping(value = "/fetchTreeNode", method = RequestMethod.POST)
    public @ResponseBody Object fetchTreeNode(ParentIdFaceRequest faceReq, CheckResult cr, Trace t, ISimpleUser su) {
        // check(t, "fetchTreeNode", faceReq, su);

        return doFetchTreeNode(faceReq, cr, t, su);
    }

    private Object doFetchTreeNode(ParentIdFaceRequest faceReq, CheckResult cr, Trace t, ISimpleUser su) {
        if (faceReq.getId() == null || Strings.isBlank(faceReq.getUuid())) {
            throw new BizException(Exceptions.CODE_ERROR_PARAMETER, "参数错误");
        }
        T entity = doFetch(t, faceReq, su, cr);
        return entity.toTreeNode();
    }

    @Face(simple = true)
    @RequestMapping(value = "/fetchParentTreeNode", method = RequestMethod.POST)
    public @ResponseBody Object fetchParentTreeNode(ParentIdFaceRequest faceReq, CheckResult cr, Trace t,
            ISimpleUser su) {
        // check(t, "fetchParentTreeNode", faceReq, su);
        return doFetchParentTreeNode(faceReq, cr, t, su);
    }

    private Object doFetchParentTreeNode(ParentIdFaceRequest faceReq, CheckResult cr, Trace t, ISimpleUser su) {
        if (faceReq.getId() == null || Strings.isBlank(faceReq.getUuid())) {
            throw new BizException(Exceptions.CODE_ERROR_PARAMETER, "参数错误");
        }
        T entity = doFetch(t, faceReq, su, cr);
        if (entity != null) {
            T parent = manager().fetchById(t, entity.getParentId());
            if (parent != null) {
                return parent.toTreeNode();
            }
        }
        return null;
    }

}
